package com.lobov.operations;

import com.lobov.entities.Matrix;
import com.lobov.entities.Snip;
import com.lobov.entities.Timer;

public class Multiplication extends Timer {

	public static Multiplication newInstance() {
		return new Multiplication();
	}

	public Matrix matrixOnMatrix(Matrix m1, Matrix m2, boolean printLogs)
			throws Exception {
		if (m1.getXlength() != m2.getYlength()) {
			throw new Exception(
					"Ошибка !!! Количество строк в первой матрице не равно числу столбцов во второй!!! Перемножение таких матриц невозможно.");
		}
		startTimer(); // стартуем таймер сразу же при начале перемножения
		int xLengthM1 = m1.getXlength();
		int xLengthM2 = m2.getXlength();
		int yLengthM1 = m1.getYlength();
		// int yLengthM2 = m2.getYlength();
		int xLengthNew = xLengthM2;
		int yLengthNew = yLengthM1;
		Matrix newMatrix = new Matrix(xLengthNew, yLengthNew);
		int[] xs = new int[xLengthNew * yLengthNew];
		int[] ys = new int[xLengthNew * yLengthNew];
		double[] values = new double[xLengthNew * yLengthNew];
		int counter = 0;

		for (int hh = 1; hh <= yLengthM1; hh++) {
			if (printLogs) {
				System.out.println("Генерируем строку " + hh
						+ " производной матрицы ...");
			}

			for (int l2 = 1; l2 <= xLengthM2; l2++) {
				if (printLogs) {
					System.out.println("Работаем со строкой " + hh
							+ " первой матрицы и столбцом " + l2
							+ " второй матрицы  ...");
				}
				double summ = 0;
				for (int l1 = 1; l1 <= xLengthM1; l1++) {
					summ += (m1.getElementByXY(l1, hh) * m2.getElementByXY(l2,
							l1));
				}
				values[counter] = summ;
				xs[counter] = l2 - 1;
				ys[counter] = hh - 1;
				counter++;
			}
		}
		newMatrix.setValues(values);
		newMatrix.setXs(xs);
		newMatrix.setYs(ys);
		stopTimer();
		return newMatrix;
	}
	
	public Snip snipOnMatrix(Snip sp, Matrix m, boolean printLogs) throws Exception{
		if (sp.getXlength() != m.getYlength()) {
			throw new Exception(
					"Ошибка !!! Количество строк в матрице не равно числу столбцов в лоскуте!!! Перемножение таких сущностей невозможно.");
		}
		startTimer(); // стартуем таймер сразу же при начале перемножения
		int xLengthSnip = sp.getXlength();
		int xLengthMatrix = m.getXlength();
		int yLengthSnip = sp.getYlength();
		// int yLengthMatrix = m.getYlength();
		int xLengthNewSnip = xLengthMatrix;
		int yLengthNewSnip = yLengthSnip;
		int numOfOrderSnipInContainer = sp.getOrderNumInContainer();
		Snip newSnip = new Snip(xLengthNewSnip, yLengthNewSnip, numOfOrderSnipInContainer);
		int[] xs = new int[xLengthNewSnip * yLengthNewSnip];
		int[] ys = new int[xLengthNewSnip * yLengthNewSnip];
		double[] values = new double[xLengthNewSnip * yLengthNewSnip];
		int counter = 0;

		for (int hh = 1; hh <= yLengthSnip; hh++) {
			if (printLogs) {
				System.out.println("Генерируем строку " + hh
						+ " производного лоскута ...");
			}

			for (int l2 = 1; l2 <= xLengthMatrix; l2++) {
				if (printLogs) {
					System.out.println("Работаем со строкой " + hh
							+ " лоскута и столбцом " + l2
							+ " матрицы  ...");
				}
				double summ = 0;
				for (int l1 = 1; l1 <= xLengthSnip; l1++) {
					summ += (sp.getElementByXY(l1, hh) * m.getElementByXY(l2,
							l1));
				}
				values[counter] = summ;
				xs[counter] = l2 - 1;
				ys[counter] = hh - 1;
				counter++;
			}
		}
		newSnip.setValues(values);
		newSnip.setXs(xs);
		newSnip.setYs(ys);
		stopTimer();
		return newSnip;
	}
	

	public Matrix matrixOnVector() {
		return null;
	}

}
